math.randomseed(os.time())

local skynet = require "skynet"
require "skynet.manager"
local MessageType = require "common.message_type"
local service_helper = require "common.service_helper"

local CMD = {}
local SOCKET = {}
local gate
local agent

local fds = {}

function SOCKET.open(fd, addr)
    skynet.error("New client from : " .. addr)
    if fds[fd] then
        skynet.error("Error : Already open this fd:",fd)
    else
        fds[fd] = fd
        skynet.call(agent, "lua", MessageType.OnClientConnected, { gate = gate, client = fd})
    end
end

local function close_agent(_fd)
    local fd = fds[_fd]
    if fd then
        fds[fd] = nil
        skynet.call(gate, "lua", "kick", fd)
        -- disconnect never return
        skynet.send(agent, "lua", MessageType.OnClientDisconnected,fd)
    end
end

function SOCKET.close(fd)
    print("socket close",fd)
    close_agent(fd)
end

function SOCKET.error(fd, msg)
    print("socket error",fd, msg)
    close_agent(fd)
end

function SOCKET.warning(fd, size)
    -- size K bytes havn't send out in fd
    print("socket warning", fd, size)
end

function SOCKET.data(fd, msg)
end

function CMD.start(conf)
    conf = conf or {}
    conf.watchdog = skynet.self()
    skynet.call(gate, "lua", "open" , conf)
end

CMD[MessageType.DisconnectClient] = function(fd)
    close_agent(fd)
end

CMD[MessageType.Inited] = function(_agent)
    agent = _agent
end

function CMD.closeAll()
    for _,fd in ipairs(fds) do
        close_agent(fd)
    end
end

skynet.start(function()
    skynet.dispatch("lua", function(session, source, cmd, subcmd, ...)
        if cmd == "socket" then
            local f = SOCKET[subcmd]
            f(...)
            -- socket api don't need return
        else
            local f = assert(CMD[cmd])
            skynet.ret(skynet.pack(f(subcmd, ...)))
        end
    end)

    gate = skynet.newservice("gate")

    skynet.register(service_helper.services.watchdog)

end)